/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbeans;

import entities.CompteBancaire;
import entities.OperationBancaire;
import entities.TypeCompte;
import entities.Users;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.inject.Named;
import session.GestionnaireDeCompteBancaire;
import session.GestionnaireOperation;
import session.GestionnaireTypeCompte;
import session.GestionnaireUsers;

/**
 *
 * @author Cyn
 */
@Named(value = "userController")
@SessionScoped
public class UserController implements Serializable {

    /**
     * Creates a new instance of UserController
     */
    public UserController() {
        
    }
    
    
    @EJB
    private GestionnaireUsers gu;
    private Users utilisateur = new Users();
    private String nom;
    private String login;
    private String password;
    private String typeU;
    private boolean connected = false;
    private String error = "";
    private String message = "";
    private List<CompteBancaire> lesComptes = new ArrayList();
    private Users uSelect = new Users();

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Users getUtilisateur() {
        return utilisateur;
    }

    public void setUtilisateur(Users utilisateur) {
        this.utilisateur = utilisateur;
    }

    public boolean isConnected() {
        return connected;
    }

    public void setConnected(boolean connected) {
        this.connected = connected;
    }
    
    public void deconnexion() {
        this.utilisateur = new Users();
        this.connected = false;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }

    public String getTypeU() {
        return typeU;
    }

    public void setTypeU(String typeU) {
        this.typeU = typeU;
    }

    public List<CompteBancaire> getLesComptes() {
        return lesComptes;
    }

    public void setLesComptes(List<CompteBancaire> lesComptes) {
        this.lesComptes = lesComptes;
    }

    public Users getUSelect() {
        return uSelect;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    public void setUSelect(Users uSelect) {
        this.uSelect = uSelect;
    }
   
    private Converter userConverter = new Converter() {  
  
        @Override
        public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {  
            if (submittedValue.trim().equals("")) {  
                return null;  
            } 
            else {  
                try {  
                    String unNom = submittedValue;  

                    for (Users u : getAllUsers()) {  
                        if (u.getNom().equals(unNom)){  
                            return u;  
                        }  
                    }  

                } catch(NumberFormatException exception) {  
                    throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error", "Not a valid player"));  
                }  
            }  

            return null;  
        }  

        @Override
        public String getAsString(FacesContext facesContext, UIComponent component, Object value) {  
            if (value == null || value.equals("")) {  
                return "";  
            } else {  
                Users u = (Users) value;
                return u.getNom();  
            }  
        }  
    };
    
    public Converter getUserConverter() {  
        return userConverter;  
    }
    
    public List<String> completeUsers(String query) {
        List<String> suggestions = new ArrayList<String>();  
          
        for(Users u : getAllUsers()) {  
            if(u.getNom().startsWith(query))  
                suggestions.add(u.getNom());  
        }  
          
        return suggestions;  
    }  
    
    public String checkLogin() {
        this.error = "";
        System.out.println("login : "+this.utilisateur.getLogin());
        System.out.println("==ManagedBean==");
        String adresse = "";
        /*if(gu.authentification(login, password)){
            utilisateur = gu.trouverLogin(login);
            connected = true;
            adresse = "index";
        }*/
        this.utilisateur = gu.authentification(this.utilisateur.getLogin(), this.utilisateur.getPwd());
        if(this.utilisateur != null){
            System.out.println("########## compte trouvé");
            this.connected = true;
            this.message = "Vous vous êtes connecté avec succés.";
            adresse ="index?faces-redirect=true";
        }
        else
        {
            this.utilisateur = new Users();
            this.error = "Vous avez saisi un mauvais mot de passe ou un mauvais login !";
            this.connected = false;
            adresse = "login?faces-redirect=true";
        }
        return adresse;
    }
    
    public String createUserAction() {
        System.out.println("Création utilisateur : "+this.nom+"; "+this.login+"; "+this.password+"; "+this.typeU);
        Users u = new Users(this.nom, this.login, this.password, this.typeU);
        gu.ajouter(u);
        this.message = "L'utilisateur a bien été créé.";
        return "index?faces-redirect=true";
    }
    
    public String updateUserAction(){
        gu.update(this.utilisateur);
        this.message = "L'utilisateur a bien été mis à jour.";
        return "index?faces-redirect=true";
    }
    
    public int getTotal(){
        int total = 0;
        for(CompteBancaire c : this.utilisateur.getComptes()) {  
            total += c.getSolde();  
        }  
        return total;
    }
    
    public int getTotalComptes(){
        int total = 0;
        for(CompteBancaire c : this.lesComptes) {  
            total += c.getSolde();  
        }  
        return total;
    }
    
    public List<Users> getAllUsers(){
        List<Users> utilisateurs = gu.getAllUsers();
        
        return utilisateurs;        
    }
    
    public String showComptes(Users u){
        this.uSelect = u;
        this.lesComptes = u.getComptes();
        return "compte_show?faces-redirect=true";
    }
    
    public Users getUserByCompte(CompteBancaire c){
        return gu.getUserByCompte(c);
    }
    
    //=================Compte Bancaire=================//
    @EJB
    private GestionnaireDeCompteBancaire gc;
    private Users debiteur;
    private CompteBancaire compteDebite;
    private List<CompteBancaire> listeDebiteur;
    private Users crediteur;
    private CompteBancaire compteCredite;
    private List<CompteBancaire> listeCrediteur;
    private Users selectU;
    private int solde;
    private TypeCompte typeC;
    private Converter compteConverter = new Converter() {  
  
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            String[] cptId = value.split(":"); 
            System.out.println("ID : "+cptId[0]);
            CompteBancaire cb = gc.getCompteById(Long.parseLong(cptId[0]));
            System.out.println("Compte : "+cb.getId()+" libelle : "+cb.getType().getLibelleType());
            return cb;  
        }

        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            CompteBancaire cb = (CompteBancaire)value;
            return cb.getId()+": "+cb.getType().getLibelleType()+" -> "+cb.getSolde()+"€";
        }
    }; 
    
    public Converter getCompteConverter() {  
        return compteConverter;  
    }  
    
    public CompteBancaire getCompteCredite() {
        return compteCredite;
    }

    public void setCompteCredite(CompteBancaire compteCredite) {
        this.compteCredite = compteCredite;
    }

    public CompteBancaire getCompteDebite() {
        return compteDebite;
    }

    public void setCompteDebite(CompteBancaire compteDebite) {
        this.compteDebite = compteDebite;
    }

    public Users getSelectU() {
        return selectU;
    }

    public void setSelectU(Users selectU) {
        this.selectU = selectU;
    }

    public int getSolde() {
        return solde;
    }

    public void setSolde(int solde) {
        this.solde = solde;
    }

    public TypeCompte getTypeC() {
        return typeC;
    }

    public void setTypeC(TypeCompte typeC) {
        this.typeC = typeC;
    }

    public List<CompteBancaire> getListeCrediteur() {
        return listeCrediteur;
    }

    public void setListeCrediteur(List<CompteBancaire> listeCrediteur) {
        this.listeCrediteur = listeCrediteur;
    }

    public List<CompteBancaire> getListeDebiteur() {
        return listeDebiteur;
    }

    public void setListeDebiteur(List<CompteBancaire> listeDebiteur) {
        this.listeDebiteur = listeDebiteur;
    }

    public Users getCrediteur() {
        return crediteur;
    }

    public void setCrediteur(Users Crediteur) {
        this.crediteur = Crediteur;
    }

    public Users getDebiteur() {
        return debiteur;
    }

    public void setDebiteur(Users debiteur) {
        this.debiteur = debiteur;
    }
    
    public String create() {
        OperationBancaire ob = new OperationBancaire("Ouverture de compte de "+this.selectU.getNom() , this.solde);
        System.out.println("nom : "+this.selectU.getNom()+"; montant : "+this.solde+"; type :"+typeC.getLibelleType());
        CompteBancaire c = new CompteBancaire(this.solde, typeC);
        c.addOperationBancaire(ob);
        this.selectU.addCompte(c);
        gu.update(this.selectU);
        this.message = "Le compte a bien été créé.";
        return "index";  
    } 
    
    public void handleChargement(){
        System.out.println("handleChargement**************************");
        List<CompteBancaire> desComptes = new ArrayList();
        for(CompteBancaire c : this.utilisateur.getComptes()){
            if(c.getId() != this.compteDebite.getId())
                desComptes.add(c);
        }
        this.listeCrediteur = desComptes;
    }
    
    public void handleChargementCrediteur(){
        if(this.crediteur != null ) {
            listeCrediteur = this.crediteur.getComptes();
        }  
        else {
            listeCrediteur = new ArrayList();
        } 
    }
    
    public void handleChargementDebiteur(){
        if(this.debiteur != null ) {
            listeDebiteur = this.debiteur.getComptes();
        }  
        else {
            listeDebiteur = new ArrayList();
        } 
    
    }
    
    public String asStringCompte(CompteBancaire c){
        return c.getId()+": "+c.getType().getLibelleType()+" -> "+c.getSolde()+"€";
    }
    
    public String virementAction(){
        System.out.println("###Méthode virement action###");
        if(!this.utilisateur.getTypeUser().equals("Admin")){
            this.crediteur = this.utilisateur;
            this.debiteur = this.utilisateur;
        }
        if(this.compteDebite.retirerArgent(this.solde)){
            String messageDebiteur = "Débit du compte numéro : "+ this.compteDebite.getId() +" de  "+this.debiteur.getNom()+" d'un montant de : "+this.solde;
            String messageCrediteur = "Credit du compte numéro : "+ this.compteCredite.getId() +" de  "+this.crediteur.getNom()+" d'un montant de : "+this.solde;
            System.out.println(messageDebiteur);
            System.out.println(messageCrediteur);
            this.compteCredite.ajouterArgent(this.solde);
            
            OperationBancaire obc = new OperationBancaire(messageCrediteur, this.solde);
            this.compteCredite.addOperationBancaire(obc);
            OperationBancaire obd = new OperationBancaire(messageDebiteur, -this.solde);
            this.compteDebite.addOperationBancaire(obd);
            gc.update(this.compteDebite);
            gc.update(this.compteCredite);
            this.compteCredite = new CompteBancaire();
            this.compteDebite = new CompteBancaire();
            this.listeCrediteur = new ArrayList();
            this.listeDebiteur = new ArrayList();
            this.solde = 0;
            this.message = "Le virement a bien été effectué.";
            this.utilisateur = gu.getUserById(this.utilisateur.getId());
            return "index?faces-redirect=true";  
        }else{
            return "virement?faces-redirect=true";
        }
    }
    
    public String operationAction(){
        System.out.println("###Méthode operation action###");
        int operation = this.compteCredite.getSolde() + this.solde;
        if(!this.utilisateur.getTypeUser().equals("Admin")){
            this.crediteur = this.utilisateur;
        }
        if(operation > 0){
            
            String messageO = "Operation sur le compte numéro : "+ this.compteCredite.getId() +" de  "+this.crediteur.getNom()+" d'un montant de : "+this.solde;
            this.compteCredite.ajouterArgent(this.solde);
            System.out.println(messageO);
            OperationBancaire obc = new OperationBancaire(messageO, this.solde);
            this.compteCredite.addOperationBancaire(obc);
            
            gc.update(this.compteCredite);
            this.message = "L'opération a bien été effectuée.";
            this.utilisateur = gu.getUserById(this.utilisateur.getId());
            this.compteCredite = new CompteBancaire();
            this.listeCrediteur = new ArrayList();
            this.solde = 0;
            return "index?faces-redirect=true";  
        }else{
            return "operation_create?faces-redirect=true";
        }
    }
    
    public List<CompteBancaire> getLazyComptes(){
        return this.uSelect.getComptes();
    }
    
    
    //=================Type compte=================//
    @EJB
    private GestionnaireTypeCompte gt;
    
    public List<TypeCompte> getAllTypeCompte(){
        List<TypeCompte> lt = gt.getAllTypeCompte();
        
        return lt;
    }
    
    private Converter typeCompteConverter = new Converter() {  
  
        @Override
        public Object getAsObject(FacesContext facesContext, UIComponent component, String submittedValue) {  
            try {  
                String unlibelle = submittedValue;  

                for (TypeCompte t : getAllTypeCompte()) {  
                    if (t.getLibelleType().equals(unlibelle)){  
                        return t;  
                    }  
                } 
                return null;
            } catch(NumberFormatException exception) {  
                return null;
            }  
            
        }

        @Override
        public String getAsString(FacesContext facesContext, UIComponent component, Object value) {
            if (value == null || value.equals("")) {  
                return "";  
            } else {  
                TypeCompte c = (TypeCompte) value;
                //return "cc"+cb.getId()+"-"+cb.getProprietaire();
                return c.getLibelleType();  
            }
        }  
    };
    
    public Converter getTypeCompteConverter() {  
        return typeCompteConverter;  
    }  
    
    public List<String> completeTypeComptes(String query) {
        List<String> suggestions = new ArrayList<String>();  
          
        for(TypeCompte t : getAllTypeCompte()) {  
            if(t.getLibelleType().startsWith(query))  
                suggestions.add(t.getLibelleType());  
        }  
          
        return suggestions;  
    }  
    
    //=================Opération Bancaire=================//
    @EJB
    GestionnaireOperation go;
    
    public List<OperationBancaire> getAllOperation(){
        return go.getAllOperations();
    }
}   
